﻿Imports System.Text
Imports System.Timers
Imports TwitterAPI
Imports System.Windows
Imports VsSpeakerCompanion
Imports System.ComponentModel.Composition
Imports System.Windows.Threading

Namespace CoolnessWidget
	''' <summary>
	''' Allows the audience to express if they think the presentation is cool or not cool.
	''' </summary>
	Friend Class CoolWidget
		Implements IWidget
		' our UI
		Private view As CoolView
		' reference to core context
		Private context As Context
		' lists to keep track of feedback
		Private coolVoters As List(Of String)
		Private notCoolVoters As List(Of String)

		Public Sub New(ByVal context As Context, ByVal twitterService As TwitterService)
			Me.context = context
            Me.view = New CoolView

            coolVoters = New List(Of String)
            notCoolVoters = New List(Of String)

			' register the two feedback messages this widget understands
			twitterService.RegisterCommand("is cool", AddressOf ProcessCoolMessages)
			twitterService.RegisterCommand("is not cool", AddressOf ProcessNotCoolMessages)
		End Sub

		''' <summary>
		''' Handles 'is cool' received messages
		''' </summary>
		''' <param name="feedItems"></param>
		Private Sub ProcessCoolMessages(ByVal feedItems As IEnumerable(Of FeedItem))
			' each user has one vote max but it can be changed anytime
			feedItems.ToList().ForEach(Sub(item)
				If notCoolVoters.Contains(item.User) Then
					notCoolVoters.Remove(item.User)
				End If
			End Sub)
            feedItems.ToList().ForEach(Sub(item)
                                           If Not coolVoters.Contains(item.User) Then
                                               coolVoters.Add(item.User)
                                           End If
                                       End Sub)
			' update UI based on new feedback
			UpdateVotesInVisualElement()
		End Sub

		''' <summary>
		''' Handles 'is not cool' received messages
		''' </summary>
		''' <param name="feedItems"></param>
		Private Sub ProcessNotCoolMessages(ByVal feedItems As IEnumerable(Of FeedItem))
			' each user has one vote max but it can be changed anytime
			feedItems.ToList().ForEach(Sub(item)
				If coolVoters.Contains(item.User) Then
					coolVoters.Remove(item.User)
				End If
			End Sub)
            feedItems.ToList().ForEach(Sub(item)
                                           If Not notCoolVoters.Contains(item.User) Then
                                               notCoolVoters.Add(item.User)
                                           End If
                                       End Sub)
			' update UI based on new feedback
			UpdateVotesInVisualElement()
		End Sub

		''' <summary>
		''' Handles the update of the five different UI possible states based on the received feeback
		''' </summary>
		Private Sub UpdateVotesInVisualElement()
            Dim coolPerc = Convert.ToDouble(coolVoters.Count) / Convert.ToDouble(coolVoters.Count + notCoolVoters.Count)
            Dim score = Convert.ToInt32(coolPerc * 40.0)
            view.Dispatcher.Invoke(New Action(Of Integer)(Sub(scoreArgument) UpdateScore(scoreArgument)), score)
			UpdateVotesInContext()
        End Sub

        Private Sub UpdateScore(ByVal value As Integer)
            view.Score = value
        End Sub

        Public ReadOnly Property VisualElement As UIElement Implements IWidget.VisualElement
            Get
                ' return our UI
                Return view
            End Get
        End Property

		''' <summary>
		''' Reset data to its original state
		''' </summary>
        Public Sub Reset() Implements IWidget.Reset
            Me.coolVoters = New List(Of String)
            Me.notCoolVoters = New List(Of String)
            UpdateVotesInContext()
            view.Score = 25
        End Sub

		''' <summary>
		''' Publish our vote count to the core context for others to consume
		''' </summary>
		''' <remarks>
		''' The StartStopSession will be reading this count
		''' </remarks>
		Private Sub UpdateVotesInContext()
			Me.context.AddProperty("coolVotes", Me.coolVoters.Count)
			Me.context.AddProperty("notCoolVotes", Me.notCoolVoters.Count)
		End Sub

	End Class
End Namespace